import std.random;
import std.stdio: writefln;
import std.math: abs;

import Digits;

public class Perceptron {
	int theta;
	int[] wagi;

	this(int size){
		wagi.length = size;
		for(int i = 0; i < size; i++)
			while(!wagi[i])
				wagi[i] = (rand() % 10) - 5;
		theta = (rand() % 10) - 5;
	}
	
	int detect(int[] input){
		int val = 0;

		for(int i = 0; i < input.length; i++)
			val += wagi[i] * input[i];
		
		if(val > theta) return 1;
		else if(val < theta) return -1;
		else return 0;
	}

    int detect2(int[] input, out float wsp){
        int val = 0;

        for(int i = 0; i < input.length; i++)
            val += wagi[i] * input[i];

       if(theta)
            wsp = abs((val - theta)/theta);
        else
            wsp = 0;

        if(val > theta) return 1;
        else if(val < theta) return -1;
        else return 0;
    }


	void train(int output, int iterations){
		int bestAge = 0;
		int currAge = 0;
		int bestWagi[] = new int[wagi.length];
		int[] input = new int[wagi.length];
		int expect;
		
		for(int i = 0; i < iterations; i++){
			int num = rand() % 10;

			assert(num >= 0);
			assert(num<10);
			
			input[] = cyfry[num];
			if(num == output)
				expect = 1;
			else
				expect = -1;

			zaburz(input);
			int eval = detect(input);
			if(eval != expect){
				currAge = 0;
				theta -= expect;
				foreach(a,inout b; wagi)
					 b += (input[a] * expect);
			}
			else{
				currAge++;
				if(currAge > bestAge){
					bestAge = currAge;
					bestWagi[] = wagi[];
				}
			}
		}

		wagi[] = bestWagi[];
		writefln(theta," ",bestAge," ", wagi);
	}

	int test(int[] input){
		int dobre = 0;
		for(int i = 0; i<1000; i++){
			int[] inp = new int[input.length];
			inp[] = input[];
			zaburz(inp);
			if(detect(inp) == 1)
				++dobre;
		}
		return dobre;
	}

	void zaburz(inout int[] a){
		for(int i = 0; i < a.length; i++){
			int prob = (rand() % 100);
			if(prob < 10)
         		a[i] = !a[i];
   		}
	}


}
